home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / util / pack / xpack_14.lha / xPack / xPack.c < prev    next >
C/C++ Source or Header  |  1993-03-25  |  11KB  |  476 lines

  1.  
  2. #include <exec/alerts.h>
  3. #include <exec/memory.h>
  4. #include <exec/execbase.h>
  5.  
  6. #include <dos/dosextens.h>
  7. #include <dos/dosasl.h>
  8. #include <dos/rdargs.h>
  9.  
  10. #include <libraries/xpk.h>
  11.  
  12. #define _USEOLDEXEC_ 1
  13.  
  14. #include <proto/dos.h>
  15. #include <proto/exec.h>
  16.  
  17. #include <string.h>
  18.  
  19. #define XFH_ID "XFH A"
  20.  
  21. void PrintF(char *,...);
  22. LONG __regargs PackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  23.                         char *,struct FileInfoBlock *,char *,char *,LONG,char *,
  24.                         LONG,LONG,LONG,LONG,LONG);
  25. LONG __regargs UnPackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  26.                           char *,char *,struct FileInfoBlock *,char *,LONG);
  27. LONG __asm __saveds ChunkFunc(register __a1 struct XpkProgress *);
  28.  
  29. struct Hook ChunkHook = {{0L},ChunkFunc};
  30.  
  31. struct xPackArgs
  32.  {
  33.   char **Files;
  34.   char *Method;
  35.   ULONG *MinSize;
  36.   char *Suffix,*Password;
  37.   LONG All,Force,Program,xScan,Lossy,Quiet;
  38.  };
  39.  
  40. char *VersionString = "$VER: xPack 1.4 ("__DATE__")";
  41. char *Template =
  42.  "FILE/M/A,METHOD/K,MINSIZE/N/K,SUFFIX/K,PASSWORD/K,"
  43.  "ALL/S,FORCE/S,PROGRAM/S,XSCAN/S,LOSSY/S,QUIET/S";
  44.  
  45. LONG __saveds main(void)
  46.  
  47. {
  48.  struct DosLibrary *DOSBase;
  49.  struct Library *XpkBase;
  50.  struct Process *MyProc;
  51.  struct RDArgs *RDArgs;
  52.  char ProgName[32];
  53.  LONG Result;
  54.  struct xPackArgs Args;
  55.  char **Files;
  56.  struct AnchorPath *AnchorPath;
  57.  ULONG MinSize;
  58.  
  59.  if ((MyProc=(struct Process *)FindTask(NULL))->pr_CLI==NULL)
  60.   {
  61.    (void)WaitPort(&MyProc->pr_MsgPort);
  62.    Forbid();
  63.    ReplyMsg (GetMsg(&MyProc->pr_MsgPort));
  64.  
  65.    return 0L;
  66.   }
  67.  
  68.  if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",33L))==NULL)
  69.   {
  70.    Alert (AT_Recovery|AG_OpenLib|AO_DOSLib);
  71.  
  72.    return 20L;
  73.   }
  74.  if (DOSBase->dl_lib.lib_Version<37L)
  75.   {
  76.    (void)Write(Output(),"This program requires OS 2.04 or newer.\n",40L);
  77.  
  78.    CloseLibrary (&DOSBase->dl_lib);
  79.    return 20L;
  80.   }
  81.  
  82.  if (!GetProgramName(ProgName,32L)) (void)strcpy(ProgName,"xPack");
  83.  Result=10L;
  84.  
  85.  if ((XpkBase=OpenLibrary(XPKNAME,2L))==NULL)
  86.   {
  87.    PrintF ("%s: %s V2 or newer required !\n",ProgName,XPKNAME);
  88.  
  89.    goto Close1;
  90.   }
  91.  
  92.  Args.Files=NULL;
  93.  Args.Method=Args.Suffix=Args.Password=NULL;
  94.  Args.MinSize=NULL;
  95.  Args.All=Args.Force=Args.Program=Args.xScan=Args.Lossy=Args.Quiet=FALSE;
  96.  if ((RDArgs=ReadArgs(Template,(LONG *)&Args,NULL))==NULL)
  97.   {
  98.    PrintFault (IoErr(),ProgName);
  99.  
  100.    goto Close2;
  101.   }
  102.  
  103.  if (Args.MinSize) MinSize=*Args.MinSize;
  104.  else MinSize=512L;
  105.  if (Args.Password) Args.Force=TRUE;
  106.  
  107.  if ((AnchorPath=(struct AnchorPath *)AllocVec(sizeof(struct AnchorPath)+256L,
  108.                                                MEMF_PUBLIC|MEMF_CLEAR))==NULL)
  109.   {
  110.    PrintFault (ERROR_NO_FREE_STORE,ProgName);
  111.  
  112.    goto Close3;
  113.   }
  114.  AnchorPath->ap_BreakBits=SIGBREAKF_CTRL_C;
  115.  AnchorPath->ap_Strlen=256;
  116.  
  117.  Files=Args.Files;
  118.  while (*Files)
  119.   {
  120.    LONG RetVal;
  121.  
  122.    for (RetVal=MatchFirst(*Files,AnchorPath); RetVal==0L; RetVal=MatchNext(AnchorPath))
  123.     {
  124.      if (AnchorPath->ap_Info.fib_DirEntryType>0L)
  125.       {
  126.        if (((AnchorPath->ap_Flags&APF_DIDDIR)==0L)&&Args.All)
  127.         AnchorPath->ap_Flags|=APF_DODIR;
  128.        AnchorPath->ap_Flags&=~APF_DIDDIR;
  129.       }
  130.      else
  131.       {
  132.        BPTR DirLock;
  133.        LONG Result;
  134.  
  135.        DirLock=CurrentDir(AnchorPath->ap_Current->an_Lock);
  136.        if (Args.Method==NULL)
  137.         Result=UnPackFile(DOSBase,XpkBase,
  138.                           AnchorPath->ap_Buf,Args.Suffix,&AnchorPath->ap_Info,
  139.                           Args.Password,Args.Quiet);
  140.        else
  141.         Result=PackFile(DOSBase,XpkBase,
  142.                         AnchorPath->ap_Buf,&AnchorPath->ap_Info,Args.Method,
  143.                         Args.Suffix,MinSize,Args.Password,
  144.                         Args.Force,Args.Program,Args.xScan,Args.Lossy,Args.Quiet);
  145.        (void)CurrentDir(DirLock);
  146.  
  147.        if (!Result)
  148.         {
  149.          PrintF ("\n*** Aborting\n");
  150.  
  151.          MatchEnd (AnchorPath);
  152.          goto Close4;
  153.         }
  154.       }
  155.     }
  156.    MatchEnd (AnchorPath);
  157.  
  158.    if (RetVal!=ERROR_NO_MORE_ENTRIES)
  159.     {
  160.      PrintF ("%s: %s - ",ProgName,*Files);
  161.      PrintFault (RetVal,NULL);
  162.      
  163.      goto Close4;
  164.     }
  165.    else Files++;
  166.   }
  167.  Result=0L;
  168.  
  169. Close4: /* I hate "goto"s, but it's the only way to keep it short. */
  170.  FreeVec ((APTR)AnchorPath);
  171. Close3:
  172.  FreeArgs (RDArgs);
  173. Close2:
  174.  CloseLibrary (XpkBase);
  175. Close1:
  176.  CloseLibrary (&DOSBase->dl_lib);
  177.  return Result;
  178. }
  179.  
  180. void PrintF(char *FormatString,...)
  181.  
  182. {
  183.  struct DosLibrary *DOSBase;
  184.  
  185.  if (DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L))
  186.   {
  187.    (void)VPrintf(FormatString,(LONG *)&FormatString+1L);
  188.    (void)Flush(Output());
  189.  
  190.    CloseLibrary (&DOSBase->dl_lib);
  191.   }
  192. }
  193.  
  194. void __regargs TempName(char *Name)
  195.  
  196. {
  197.  UWORD Index;
  198.  ULONG Addr;
  199.  
  200.  for (Index=0, Addr=(ULONG)FindTask(NULL); Index<8; Index++, Addr>>=4)
  201.   *Name++='A'+(char)(Addr&15);
  202.  (void)strcpy(Name,".zop");
  203. }
  204.  
  205. LONG __asm __saveds ChunkFunc(register __a1 struct XpkProgress *Prog)
  206.  
  207. {
  208.  if (Prog->Type==XPKPROG_START ) PrintF ("\x1B[0 p");
  209.  PrintF ("\r%-9s %-12s (%6ld bytes, %3ld%% done, %2ld%% CF) ",
  210.          Prog->Activity,Prog->FileName,Prog->ULen,Prog->Done,Prog->CF);
  211.  if (Prog->Type==XPKPROG_END) PrintF ("\n\x1B[1 p");
  212.  
  213.  return (LONG)SetSignal(0L,SIGBREAKF_CTRL_C)&SIGBREAKF_CTRL_C;
  214. }
  215.  
  216. char *ULTA(char *Ptr,ULONG LW)
  217.  
  218. {
  219.  UWORD Index;
  220.  
  221.  *Ptr++=' ';
  222.  for (Index=0; Index<8; Index++, LW>>=4) Ptr[7-Index]='A'+(char)(LW&15);
  223.  return &Ptr[8];
  224. }
  225.  
  226. #define TAGIT(i,t,d) XpkTags[i].ti_Tag=t; XpkTags[i].ti_Data=(ULONG)d;
  227. #define ENDIT(i) XpkTags[i].ti_Tag=TAG_DONE;
  228.  
  229. LONG __regargs PackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  230.                         char *SourceName,struct FileInfoBlock *FIB,char *Method,
  231.                         char *Suffix,LONG MinSize,char *Password,
  232.                         LONG Force,LONG Program,LONG xScan,LONG Lossy,LONG Quiet)
  233.  
  234. {
  235.  BPTR Handle;
  236.  struct TagItem XpkTags[10];
  237.  struct XpkFib XpkFib;
  238.  char ErrorBuffer[XPKERRMSGSIZE],TargetName[108];
  239.  LONG Error,Size;
  240.  
  241.  if (FIB->fib_Protection&FIBF_DELETE)
  242.   {
  243.    PrintF ("Skipping %s (delete protected)\n",SourceName);
  244.    return TRUE;
  245.   }
  246.  if (FIB->fib_Size<=MinSize)
  247.   {
  248.    PrintF ("Skipping %s (too small)\n",SourceName);
  249.    return TRUE;
  250.   }
  251.  if ((Handle=Open(FIB->fib_FileName,MODE_OLDFILE))==NULL)
  252.   {
  253.    PrintF ("Can't open %s\n",SourceName);
  254.    return TRUE;
  255.   }
  256.  if (!Force)
  257.   {
  258.    TAGIT(0,XPK_GetError,ErrorBuffer);
  259.    TAGIT(1,XPK_InFH,Handle);
  260.    ENDIT(2);
  261.    if (XpkExamine(&XpkFib,XpkTags))
  262.     {
  263.      Close (Handle);
  264.  
  265.      PrintF ("%s\n",ErrorBuffer);
  266.      return TRUE;
  267.     }
  268.    if (XpkFib.Type!=XPKTYPE_UNPACKED)
  269.     {
  270.      Close (Handle);
  271.  
  272.      PrintF ("Skipping %s (already crunched)\n",SourceName);
  273.      return TRUE;
  274.     }
  275.   }
  276.  if (Program)
  277.   {
  278.    LONG Buffer[5];
  279.  
  280.    if (Read(Handle,Buffer,20L)!=20L)
  281.     {
  282.      Close (Handle);
  283.  
  284.      PrintF ("Skipping %s (to small for executable)\n",SourceName);
  285.      return TRUE;
  286.     }
  287.    if (Buffer[0]!=0x3F3L)
  288.     {
  289.      Close (Handle);
  290.  
  291.      PrintF ("Skipping %s (not executable)\n",SourceName);
  292.      return TRUE;
  293.     }
  294.    if ((Buffer[3]!=0L)||((Buffer[4]+1L)!=Buffer[2]))
  295.     {
  296.      Close (Handle);
  297.  
  298.      PrintF ("Skipping %s (overlayed)\n",SourceName);
  299.      return TRUE;
  300.     }
  301.    (void)Seek(Handle,0L,OFFSET_BEGINNING);
  302.   }
  303.  
  304.  if (Suffix)
  305.   {
  306.    ULONG Length;
  307.  
  308.    Length=strlen(strcpy(TargetName,FIB->fib_FileName));
  309.    (void)strcpy(&TargetName[Length],Suffix);
  310.   }
  311.  else TempName (TargetName);
  312.  Size=0L;
  313.  
  314.  TAGIT(0,XPK_GetError,ErrorBuffer);
  315.  TAGIT(1,XPK_Password,Password);
  316.  TAGIT(2,XPK_FindMethod,Method);
  317.  TAGIT(3,XPK_ChunkHook,&ChunkHook);
  318.  if (Quiet) XpkTags[3].ti_Tag=TAG_IGNORE;
  319.  TAGIT(4,XPK_FileName,FIB->fib_FileName);
  320.  TAGIT(5,XPK_InFH,Handle);
  321.  TAGIT(6,XPK_OutName,TargetName);
  322.  TAGIT(7,XPK_GetOutLen,&Size);
  323.  TAGIT(8,XPK_LossyOK,Lossy);
  324.  ENDIT(9);
  325.  
  326.  if (Error=XpkPack(XpkTags))
  327.   {
  328.    Close (Handle);
  329.  
  330.    PrintF ("%s\n",ErrorBuffer);
  331.    return (Error!=XPKERR_ABORTED);
  332.   }
  333.  Close (Handle);
  334.  
  335.  if ((Size>FIB->fib_Size)&&(!Force))
  336.   {
  337.    (void)DeleteFile(TargetName);
  338.  
  339.    PrintF ("Skipping %s (unable to reduce size)\n",SourceName);
  340.    return TRUE;
  341.   }
  342.  
  343.  if (FIB->fib_Comment[0]=='\0')
  344.   if (xScan)
  345.    {
  346.     char *Ptr;
  347.  
  348.     Ptr=strcpy(FIB->fib_Comment,XFH_ID)+strlen(XFH_ID);
  349.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Days);
  350.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Minute);
  351.     Ptr=ULTA(Ptr,FIB->fib_Date.ds_Tick);
  352.     Ptr=ULTA(Ptr,Size);
  353.     *ULTA(Ptr,FIB->fib_Size)='\0';
  354.    }
  355.  
  356.  if (FIB->fib_Comment[0]) (void)SetComment(TargetName,FIB->fib_Comment);
  357.  
  358.  if (FIB->fib_Protection) (void)SetProtection(TargetName,FIB->fib_Protection);
  359.  (void)SetFileDate(TargetName,&FIB->fib_Date);
  360.  
  361.  if (Suffix) return TRUE;
  362.  
  363.  if (!DeleteFile(FIB->fib_FileName))
  364.   {
  365.    (void)DeleteFile(TargetName);
  366.  
  367.    PrintF ("Unable to delete %s\n",SourceName);
  368.    return TRUE;
  369.   }
  370.  if (!Rename(TargetName,FIB->fib_FileName))
  371.   {
  372.    PrintF ("Unable to rename %s to %s\n",TargetName,FIB->fib_FileName);
  373.    return FALSE;
  374.   }
  375.  
  376.  return TRUE;
  377. }
  378.  
  379. LONG __regargs UnPackFile(struct DosLibrary *DOSBase,struct Library *XpkBase,
  380.                           char *SourceName,char *Suffix,
  381.                           struct FileInfoBlock *FIB,char *Password,LONG Quiet)
  382.  
  383. {
  384.  BPTR Handle;
  385.  struct TagItem XpkTags[7];
  386.  struct XpkFib XpkFib;
  387.  char ErrorBuffer[XPKERRMSGSIZE],TargetName[108];
  388.  LONG SameFile,Error;
  389.  
  390.  if (FIB->fib_Protection&FIBF_DELETE)
  391.   {
  392.    PrintF ("Skipping %s (delete protected)\n",SourceName);
  393.    return TRUE;
  394.   }
  395.  if ((Handle=Open(FIB->fib_FileName,MODE_OLDFILE))==NULL)
  396.   {
  397.    PrintF ("Can't open %s\n",SourceName);
  398.    return TRUE;
  399.   }
  400.  
  401.  TAGIT(0,XPK_GetError,ErrorBuffer);
  402.  TAGIT(1,XPK_InFH,Handle);
  403.  ENDIT(2);
  404.  
  405.  if (XpkExamine(&XpkFib,XpkTags))
  406.   {
  407.    Close (Handle);
  408.  
  409.    PrintF ("%s\n",ErrorBuffer);
  410.    return TRUE;
  411.   }
  412.  if (XpkFib.Type!=XPKTYPE_PACKED)
  413.   {
  414.    Close (Handle);
  415.  
  416.    PrintF ("Skipping %s (not crunched)\n",SourceName);
  417.    return TRUE;
  418.   }
  419.  
  420.  TempName (TargetName);
  421.  SameFile=TRUE;
  422.  if (Suffix)
  423.   {
  424.    LONG Len1,Len2;
  425.  
  426.    Len1=strlen(FIB->fib_FileName);
  427.    Len2=strlen(Suffix);
  428.    if (Len1>Len2)
  429.     if (stricmp(&FIB->fib_FileName[Len1-Len2],Suffix)==0)
  430.      {
  431.       strcpy(TargetName,FIB->fib_FileName)[Len1-Len2]='\0';
  432.       SameFile=FALSE;
  433.      }
  434.   }
  435.  
  436.  TAGIT(0,XPK_GetError,ErrorBuffer);
  437.  TAGIT(1,XPK_Password,Password);
  438.  TAGIT(2,XPK_ChunkHook,&ChunkHook);
  439.  if (Quiet) XpkTags[2].ti_Tag=TAG_IGNORE;
  440.  TAGIT(3,XPK_FileName,FIB->fib_FileName);
  441.  TAGIT(4,XPK_InFH,Handle);
  442.  TAGIT(5,XPK_OutName,TargetName);
  443.  ENDIT(6);
  444.  
  445.  if (Error=XpkUnpack(XpkTags))   {
  446.    Close (Handle);
  447.  
  448.    PrintF ("%s\n",ErrorBuffer);
  449.    return (Error!=XPKERR_ABORTED);
  450.   }
  451.  Close (Handle);
  452.  
  453.  if (FIB->fib_Comment[0])
  454.   if (strncmp(FIB->fib_Comment,XFH_ID,strlen(XFH_ID))!=0)
  455.    (void)SetComment(TargetName,FIB->fib_Comment);
  456.  if (FIB->fib_Protection) (void)SetProtection(TargetName,FIB->fib_Protection);
  457.  (void)SetFileDate(TargetName,&FIB->fib_Date);
  458.  
  459.  if (!SameFile) return TRUE;
  460.  
  461.  if (!DeleteFile(FIB->fib_FileName))
  462.   {
  463.    (void)DeleteFile(TargetName);
  464.  
  465.    PrintF ("Unable to delete %s\n",SourceName);
  466.    return TRUE;
  467.   }
  468.  if (!Rename(TargetName,FIB->fib_FileName))
  469.   {
  470.    PrintF ("Unable to rename %s to %s\n",TargetName,FIB->fib_FileName);
  471.    return FALSE;
  472.   }
  473.  
  474.  return TRUE;
  475. }
  476.